Skip to content

feat: preserve normal radio profiles across event firmware - #11110

Merged
thebentern merged 13 commits into
meshtastic:developfrom
RCGV1:codex/event-channel-profile-firmware
Jul 27, 2026
Merged

feat: preserve normal radio profiles across event firmware#11110
thebentern merged 13 commits into
meshtastic:developfrom
RCGV1:codex/event-channel-profile-firmware

Conversation

@RCGV1

@RCGV1 RCGV1 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Event-only scope

This PR does not add or change channel QR behavior. Existing QR Replace and Add remain the app workflow.

What changes

  • normal firmware continues to use /prefs/config.proto, /prefs/channels.proto, and /backups/backup.proto
  • event firmware uses /prefs/event-config.proto, /prefs/event-channels.proto, and /backups/event-backup.proto
  • on its first boot, event firmware preserves the normal identity and non-radio settings, but applies the event build LoRa defaults and creates event channels from the build defaults
  • flashing back to normal firmware naturally resumes the prior channels and LoRa configuration, with no app required

Storage safety

  • first event-profile creation reserves 2,954 bytes: maximum config/channel payloads plus their full-atomic temporary files
  • if the filesystem has less space, event firmware runs from its in-memory event defaults but does not write event config or channels; this avoids saveToDisk() formatting the filesystem on a failed write
  • the next event boot retries profile creation when enough space is available
  • no extra persistent RAM is used; only the active profile is loaded
  • normal firmware removes the event config, channels, and event backup at boot, releasing all event-only storage; a later event flash starts a fresh event profile

Safety

  • event firmware never copies normal channels into the event table
  • corrupt normal config remains on the existing degraded/no-new-identity recovery path
  • encrypted-storage migration and lockdown disable cover both normal and event profile files and backups
  • backups are profile-specific

Verification

  • pio test -e native-macos -f test_event_profile_storage
  • pio run -e native-macos
  • pio run -e rak3172 (the 14 KiB STM32WL filesystem family)
  • native simulator: eight distinct AES-256 normal channels plus custom 250 kHz/SF9/CR6 LoRa -> official Open Sauce 2026 two-channel US Short Turbo/channel-31 profile -> normal firmware; normal config and channel files had identical SHA-256 hashes before, during, and after the event boot
  • full aggregate native suite was started but intentionally stopped because it rebuilds each of 38 test targets independently; focused coverage and both relevant target builds completed successfully

Design background: meshtastic/design#120 (comment)

Summary by CodeRabbit

  • New Features
    • Added event-mode–specific configuration, channel, and backup storage, including preflight checks to ensure safe atomic event-profile writes.
    • Automatically derives an event configuration from the standard one while preserving identity/security details and applying event-specific radio settings.
  • Bug Fixes
    • Improved boot persistence behavior by deferring automatic saves until configuration is successfully verified, and adding safe recovery when the event configuration is missing.
    • Enhanced encrypted-storage lockdown handling by migrating the relevant standard/event radio-profile files accordingly.
  • Tests
    • Added embedded tests covering file isolation, identity preservation, capacity boundaries, and boot persistence deferral/recovery.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Event-mode radio profiles now use dedicated persistence files. Boot loading initializes missing event configuration from the standard profile, tracks storage availability and config readiness, defers unsafe writes, and includes event files in encrypted-storage migrations. Unity tests cover the new helpers and storage rules.

Changes

Event profile persistence

Layer / File(s) Summary
Profile paths and configuration helpers
src/mesh/NodeDB.h, test/test_event_profile_storage/test_main.cpp
Adds standard/event storage path selection, event configuration derivation, storage reservation checks, boot-defer predicates, and Unity coverage.
Boot profile recovery and persistence
src/mesh/NodeDB.cpp, src/mesh/NodeDB.h
Detects missing or space-constrained event storage, derives missing event configuration, tracks config readiness, and defers or suppresses boot-time writes.
Encrypted-storage profile migration
src/mesh/NodeDB.cpp
Includes event config, channel, and backup files in encrypted-storage and plaintext migration passes.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant NodeDB
  participant Storage
  participant StandardConfig
  participant EventConfig
  NodeDB->>Storage: Check event profile file and available space
  NodeDB->>StandardConfig: Load standard configuration when event config is missing
  StandardConfig-->>NodeDB: Return configuration and decode status
  NodeDB->>EventConfig: Derive event LoRa configuration
  NodeDB->>EventConfig: Persist initial event configuration
  NodeDB->>Storage: Defer or suppress boot writes when recovery is incomplete
Loading

Possibly related issues

  • meshtastic/Meshtastic-Apple#2133 — Related to event/standard radio-profile configuration persistence and restoration across profile transitions.

Suggested reviewers: vidplace7, thebentern, jp-bennett

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change.
Description check ✅ Passed The PR description is thorough and covers scope, behavior, storage safety, safety, and verification, matching the template's intent.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

⚡ Try this PR in the Web Flasher

Flash this PR in the Web Flasher

firmware commit boards expires

Warning

This is an automated, unreviewed CI test build. Back up your device configuration
before flashing, and only flash devices you are able to recover.

Supported boards built by this PR (31)
Device Board Platform
Crowpanel Adv 3.5 TFT elecrow-adv-35-tft esp32-s3
Heltec HT62 heltec-ht62-esp32c3-sx1262 esp32-c3
Heltec Mesh Node 096 heltec-mesh-node-t096 nrf52840
Heltec Mesh Node T1 heltec-mesh-node-t1 nrf52840
Heltec Mesh Node T114 heltec-mesh-node-t114 nrf52840
Heltec V3 heltec-v3 esp32-s3
Heltec V4 heltec-v4 esp32-s3
Meshnology W10 meshnology_w10 esp32-s3
Meshnology W12 meshnology_w12 esp32-s3
Raspberry Pi Pico pico rp2040
Raspberry Pi Pico W picow rp2040
RAK WisMesh Pocket V3 rak_wismesh_pocket nrf52840
RAK WisMesh Pod rak_wismesh_pod nrf52840
RAK WisMesh Repeater Mini V2 rak_wismesh_repeater_mini nrf52840
RAK WisMesh Tag rak_wismeshtag nrf52840
RAK WisBlock 11200 rak11200 esp32
RAK WisBlock 11310 rak11310 rp2040
RAK3312 rak3312 esp32-s3
RAK WisBlock 4631 rak4631 nrf52840
Seeed SenseCAP Mesh-Tracker-X1 seeed_mesh_tracker_X1 nrf52840
Seeed Wio Tracker L1 seeed_wio_tracker_L1 nrf52840
Seeed Xiao NRF52840 Kit seeed_xiao_nrf52840_kit nrf52840
Seeed Xiao ESP32-S3 seeed-xiao-s3 esp32-s3
Station G2 station-g2 esp32-s3
Station G3 station-g3 esp32-s3
LILYGO T-Deck t-deck-tft esp32-s3
LILYGO T-Echo t-echo nrf52840
LILYGO T-Echo Plus t-echo-plus nrf52840
LILYGO T-Impulse Plus t-impulse-plus nrf52840
LilyGo T3-C6 tlora-c6 esp32-c6
Seeed SenseCAP T1000-E tracker-t1000-e nrf52840

Build artifacts expire on 2026-08-25. Updated for 6c9c2db.

@RCGV1
RCGV1 force-pushed the codex/event-channel-profile-firmware branch from b5919c4 to 65f92fc Compare July 20, 2026 20:07
@RCGV1

RCGV1 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

Review follow-up: force-pushed 65f92fca with three fixes before broad review:

  • decrypt/migrate both normal and event profile files plus their backups across lockdown transitions
  • preserve DECODE_FAILED when the normal config is corrupt during first event boot, retaining the existing degraded/no-new-identity behavior
  • isolate event backups at /backups/event-backup.proto so normal restore cannot consume event data

The draft remains blocked only on hardware verification and the existing macOS native-test argp.h host-toolchain failure.

@RCGV1
RCGV1 force-pushed the codex/event-channel-profile-firmware branch from 65f92fc to 0bc1176 Compare July 20, 2026 20:14
@RCGV1

RCGV1 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

Updated to 0bc11766: applied the repository Trunk formatter; trunk fmt src/mesh/NodeDB.cpp now reports no issues.

The remaining check-label failure is metadata-only. My fork token cannot add labels to the upstream PR; could a maintainer add enhancement? The build/test matrix is still running.

@RCGV1

RCGV1 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

macOS native simulator verification on 0bc11766 (same persistent VFS, no erase between firmware images):

  • regular firmware first boot created /prefs/config.proto and /prefs/channels.proto
  • event firmware boot loaded the ordinary config, logged Initialized event config without modifying /prefs/config.proto, created /prefs/event-config.proto and /prefs/event-channels.proto, and ran the compiled US / EventSim / SHORT_FAST radio profile
  • regular firmware booted again and loaded the original ordinary config and channels, resuming UNSET / LongFast
  • the ordinary config and channel SHA-256 values were identical before the event boot and after the return:
    • config: 9582708236b98ecd5ba5b4db7e74a2850cbe09c4661bc2531666cc890795a299
    • channels: d2b27729b144786829d0175c6e6dbc029a7bd735baf20ef49d310cc3f33e8bdf

The stable PKI-derived node number also remained 0x3678de25; the different number at fresh normal first boot was the expected pre-PKI MAC-derived provisional ID. No source changes from this verification.

@RCGV1

RCGV1 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

Follow-up verification found and fixed a real degraded-boot persistence bug.

When the normal config was corrupt on the first event boot, the original change kept config.proto and channels.proto intact but still rewrote device.proto and nodes.proto. That could change the saved node identity despite the intended "freezing identity" behavior.

This update defers automatic protobuf writes during initialization until config loading is verified. A decode-failed boot now remains degraded and radio-silent without writing normal files, event profile files, device state, or the node database. Explicit runtime configuration saves remain available after initialization.

Verification:

  • TDD: added the focused boot-persistence regression test; pio test -e native-macos -f test_event_profile_storage passes (4 tests).
  • Built both normal and event-configured native-macos firmware successfully.
  • Native simulator: normal -> event -> normal retains the separate profiles and expected radio settings.
  • Corrupt normal config before the first event boot: config, channels, device state, and node database hashes stayed unchanged; no event config or channels file was created.
  • Corrupt existing event config: normal config/channels/device/node hashes stayed unchanged, and the corrupt event config was not replaced.

The event-only userPrefs file used for the simulator remains a local test fixture and is not part of the PR.

@RCGV1
RCGV1 marked this pull request as ready for review July 20, 2026 21:33
@RCGV1

RCGV1 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

@jp-bennett @vidplace7 Please review

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/mesh/NodeDB.h (2)

115-117: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Condense code comments to comply with maximum length guidelines.

As per coding guidelines, code comments in C++ files should be minimal—one or two lines maximum.

  • src/mesh/NodeDB.h#L115-L117: Condense this 3-line comment to one or two lines.
  • src/mesh/NodeDB.h#L137-L139: Condense this 3-line comment to one or two lines.
  • src/mesh/NodeDB.h#L583-L585: Condense this 3-line comment to one or two lines.
  • src/mesh/NodeDB.cpp#L2172-L2174: Condense this 3-line comment to one or two lines.
  • src/mesh/NodeDB.cpp#L2399-L2402: Condense this 4-line comment to one or two lines.
  • src/mesh/NodeDB.cpp#L2610-L2612: Condense this 3-line comment to one or two lines.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mesh/NodeDB.h` around lines 115 - 117, Condense the comments at
src/mesh/NodeDB.h lines 115-117, 137-139, and 583-585, and src/mesh/NodeDB.cpp
lines 2172-2174, 2399-2402, and 2610-2612 to one or two lines each while
preserving their existing meaning; no code behavior changes are needed.

Source: Coding guidelines


118-123: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use UPPER_SNAKE_CASE for constants.

As per coding guidelines, C++ constants and defines must use UPPER_SNAKE_CASE.

  • src/mesh/NodeDB.h#L118-L123: Rename these filename constants to UPPER_SNAKE_CASE (e.g., STANDARD_CONFIG_FILE_NAME).
  • src/mesh/NodeDB.h#L140-L140: Rename eventProfileStorageReservationBytes to EVENT_PROFILE_STORAGE_RESERVATION_BYTES.
  • src/mesh/NodeDB.h#L161-L165: Rename radioProfileStorage to RADIO_PROFILE_STORAGE on lines 162 and 164.

(Note: If you decide to rename eventProfileStorageReservationBytes, you will also need to update its downstream usages, such as in test/test_event_profile_storage/test_main.cpp)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mesh/NodeDB.h` around lines 118 - 123, Rename the filename constants in
src/mesh/NodeDB.h lines 118-123 to UPPER_SNAKE_CASE, including
STANDARD_CONFIG_FILE_NAME and corresponding channel, event, and backup names.
Rename eventProfileStorageReservationBytes to
EVENT_PROFILE_STORAGE_RESERVATION_BYTES at line 140 and update all downstream
references, including test/test_event_profile_storage/test_main.cpp. Rename
radioProfileStorage to RADIO_PROFILE_STORAGE at lines 161-165 and update its
references.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/mesh/NodeDB.h`:
- Around line 115-117: Condense the comments at src/mesh/NodeDB.h lines 115-117,
137-139, and 583-585, and src/mesh/NodeDB.cpp lines 2172-2174, 2399-2402, and
2610-2612 to one or two lines each while preserving their existing meaning; no
code behavior changes are needed.
- Around line 118-123: Rename the filename constants in src/mesh/NodeDB.h lines
118-123 to UPPER_SNAKE_CASE, including STANDARD_CONFIG_FILE_NAME and
corresponding channel, event, and backup names. Rename
eventProfileStorageReservationBytes to EVENT_PROFILE_STORAGE_RESERVATION_BYTES
at line 140 and update all downstream references, including
test/test_event_profile_storage/test_main.cpp. Rename radioProfileStorage to
RADIO_PROFILE_STORAGE at lines 161-165 and update its references.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 61751f2f-a470-48cb-b8d8-0ce8f8aa548a

📥 Commits

Reviewing files that changed from the base of the PR and between 0199a1f and dc6033e.

📒 Files selected for processing (3)
  • src/mesh/NodeDB.cpp
  • src/mesh/NodeDB.h
  • test/test_event_profile_storage/test_main.cpp

Comment thread src/mesh/NodeDB.h Outdated
@caveman99 caveman99 added the enhancement New feature or request label Jul 21, 2026
Comment thread src/mesh/NodeDB.cpp
@jp-bennett

Copy link
Copy Markdown
Collaborator

In general I really think this is the right approach.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/mesh/NodeDB.cpp (2)

2183-2202: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Reset eventProfileStorageUnavailable on every load.

The flag is assigned only when eventConfigMissing is true. After a prior capacity failure, a repeated loadFromDisk() can retain true even after the event config exists, causing later config/channel writes to remain suppressed.

Proposed fix
 `#if` USERPREFS_EVENT_MODE
     bool eventConfigMissing = false;
+    eventProfileStorageUnavailable = false;
 `#ifdef` FSCom
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mesh/NodeDB.cpp` around lines 2183 - 2202, Reset
eventProfileStorageUnavailable at the start of each load in the
USERPREFS_EVENT_MODE initialization flow, before checking eventConfigMissing, so
a successful reload clears any prior capacity-failure state. Preserve the
existing storage-space calculation and error logging for missing configurations.

2618-2644: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Propagate EncryptedStorage::migrateFile() failures here. It returns false on read/encrypt/write errors; ignoring that can leave these files plaintext while lockdown stays active.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mesh/NodeDB.cpp` around lines 2618 - 2644, Check the return value of
EncryptedStorage::migrateFile() in both the backup migration and inactive radio
profile loop, and propagate failure through the surrounding save/migration flow.
Do not continue as if migration succeeded when it returns false, ensuring
lockdown cannot proceed while any targeted file remains plaintext.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/mesh/NodeDB.cpp`:
- Around line 2183-2202: Reset eventProfileStorageUnavailable at the start of
each load in the USERPREFS_EVENT_MODE initialization flow, before checking
eventConfigMissing, so a successful reload clears any prior capacity-failure
state. Preserve the existing storage-space calculation and error logging for
missing configurations.
- Around line 2618-2644: Check the return value of
EncryptedStorage::migrateFile() in both the backup migration and inactive radio
profile loop, and propagate failure through the surrounding save/migration flow.
Do not continue as if migration succeeded when it returns false, ensuring
lockdown cannot proceed while any targeted file remains plaintext.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 312c0ef7-e6dc-490c-a27f-6ae20c79bd0a

📥 Commits

Reviewing files that changed from the base of the PR and between c29f228 and fed61a8.

📒 Files selected for processing (1)
  • src/mesh/NodeDB.cpp

@thebentern
thebentern requested a review from Copilot July 26, 2026 11:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an “event firmware” radio-profile isolation mechanism so event builds use separate on-device config/channel/backup files, allowing users to flash back to normal firmware and automatically resume their prior LoRa + channel configuration without app intervention.

Changes:

  • Added radio-profile–scoped storage paths (standard vs event) for config/channels/backups, and helpers for seeding an event config from the standard identity while applying event LoRa defaults.
  • Implemented event-profile creation + storage-space preflight and event-file cleanup in normal firmware.
  • Added a focused native test suite covering storage-path selection, identity preservation, persistence deferral, and the reservation-space check.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
test/test_event_profile_storage/test_main.cpp Adds unit tests validating path isolation, event config derivation, persistence deferral logic, and storage-space preflight.
src/mesh/NodeDB.h Defines standard/event storage filenames and helper utilities to select paths, seed event config, and gate boot persistence.
src/mesh/NodeDB.cpp Wires profile selection into load/save flows, seeds missing event config from standard config, migrates backups for encrypted storage, and adds boot-write deferral + event-space gating.

Comment thread src/mesh/NodeDB.cpp Outdated
thebentern and others added 4 commits July 26, 2026 09:05
…tems

The USERPREFS_EVENT_MODE storage preflight called FSCom.totalBytes() and
FSCom.usedBytes(), which only exist on ESP32's LittleFS wrapper. Every other
backend failed to compile once event mode was enabled:

  error: 'class InternalFileSystem' has no member named 'totalBytes'   (nRF52)
  error: no member named 'totalBytes' in 'fs::FS'                      (Portduino)

This was not caught earlier because the event block is behind
#if USERPREFS_EVENT_MODE, and the existing unit tests only cover the pure
helpers, which compile identically either way.

Add fsTotalBytes()/fsUsedBytes() to FSCommon and implement them per backend:
littlefs v1 traversal for nRF52 (Adafruit_LittleFS) and STM32
(STM32_LittleFS), FSInfo for RP2040, statvfs for Portduino, and the native
methods for ESP32 and nRF54L15. The nRF52/STM32 path reports "full" if the
traversal errors so the capacity check fails safe.

Verified with USERPREFS_EVENT_MODE=1: native-macos test_event_profile_storage
passes 5/5, and heltec-v3, rak4631, rak11310 and rak3172 all build clean.
…uite-count

Two CI fixes:

- native-windows has no <sys/statvfs.h>, so the Portduino branch of
  fsTotalBytes()/fsUsedBytes() broke the Windows build. Switch to
  std::filesystem::space(), which is already used under ARCH_PORTDUINO in
  HostMetrics.cpp and works on both POSIX and MinGW. Errors report "full"
  so the capacity check still fails safe.

- This PR adds test/test_event_profile_storage, taking test/ from 40 to 41
  suite directories, which trips the native-suite-count reconciliation check.
…eview

Review feedback:

- Copilot: saveProto()'s boot-write deferral applied to every file, so
  loadFromDisk()'s recovery writes (e.g. restoring owner fields into
  devicestate) were silently dropped and never retried, because the ctor CRC
  baselines are computed after loadFromDisk(). Deferral now applies only to
  the radio-profile files, via isRadioProfileFile().

- jp-bennett: eventConfigFromStandard() wrapped a struct copy plus one field
  assignment in a header helper with its own unit test. Inlined at its single
  call site and removed; the behaviour is covered end-to-end by hardware
  validation instead (RAK4631 normal -> event -> normal preserves NodeNum and
  public key while swapping LoRa, and restores the original channel
  byte-identically).

- jp-bennett: the active-backup encrypted-storage migration ran for normal
  builds too, which changed non-event behaviour and contradicted the PR's
  stated event-only scope. Scoped to USERPREFS_EVENT_MODE; the adjacent block
  already covers the inactive standard backup in event builds.

New tests (all verified to fail under mutation, not vacuous):

- test_event_paths_never_collide_with_standard_or_shared_files: the core
  safety property. A path-table slip would make event firmware overwrite the
  user's real config, channels or backup, or capture a shared file like
  devicestate/nodedb. Nothing asserted this before.

- test_only_radio_profile_files_defer_boot_writes: guards the deferral fix
  above so re-widening it fails loudly.

- test_event_reservation_fits_smallest_supported_filesystem: the reservation
  is compile-time but must fit filesystems as small as 14 KiB (STM32WL) and
  28 KiB (nRF52840). Protobuf growth pushing it past those would silently
  stop event profiles persisting - the exact failure mode confirmed by
  fault injection on a RAK4631.

Verified with USERPREFS_EVENT_MODE both on and off: 7/7 tests pass, and
rak4631, heltec-v3, rak11310 and rak3172 all build clean.
@CLAassistant

CLAassistant commented Jul 26, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
3 out of 4 committers have signed the CLA.

✅ thebentern
✅ RCGV1
✅ jp-bennett
❌ Benjamin Faershtein


Benjamin Faershtein seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@thebentern
thebentern added this pull request to the merge queue Jul 26, 2026
Merged via the queue into meshtastic:develop with commit 45cb8e7 Jul 27, 2026
99 of 100 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants